<?php
namespace app\api\controller;

use app\api\logic\Coupon;
use EasyWeChat\Foundation\Application;
use EasyWeChat\Payment\Order as wechatOrder;
use EasyWeChat\Support\XML;
use think\Db;
use think\Log;

class Pay extends Base
{

    //检查权限作用域
    protected $beforeActionList  = [
        'checkPrimaryScope' => [  'only' => 'create'],
    ];


    private $config;

    /**
     * 获取微信配置
     */
    private static function getConfig(){
        $options = [
            'app_id' => config('wx.app_id'),
            'payment' => [
                'merchant_id'        => config('wx.mch_id'),
                'key'                => config('wx.key'),
                'cert_path'          => config('wx.cert_path'),      // XXX: 绝对路径！！！！
                'key_path'           => config('wx.key_path'),      // XXX: 绝对路径！！！！
                'notify_url'         => __ROOT__.'/api/pay/wechat/notify',       // 你也可以在下单时单独设置来想覆盖它
            ],
        ];
        return $options;
    }

    /**
     * 返回微信配置
     */
    public static function return_config(){
        return self::getConfig();
    }


    /**
     * 下单
     */
    public function create()
    {
        $pay_sn = $this->requestData['pay_sn'];
        if(empty($pay_sn)) return $this->ajaxReturn(['message' => '支付单号不能为空']);
        $payInfo = $this->getPayInfo($pay_sn);
        if(array_key_exists('message',$payInfo)) return $this->ajaxReturn($payInfo);
        $attributes = [
            'trade_type'       => 'JSAPI', // JSAPI，NATIVE，APP...
            'body'             =>  '购物订单',
            'detail'           =>  $payInfo['detail'],
            'out_trade_no'     =>  $payInfo['pay_sn'],
            'total_fee'        =>  $payInfo['money'], // 单位：分
            'openid'           =>  $payInfo['openid'], // trade_type=JSAPI，此参数必传，用户在商户appid下的唯一标识，
        ];
      
        $order = new wechatOrder($attributes);
        $config = self::getConfig();
        $app = new Application($config);
        $payment = $app->payment;
        $result = $payment->prepare($order);
        if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){
            $time = TIMESTAMP;
            $paySign = MD5('appId='.$result->appid.'&nonceStr='.$result->nonce_str.'&package=prepay_id='.$result->prepay_id.'&signType=MD5&timeStamp='.$time.'&key='.$config['payment']['key']);
            $data = array(
                'timeStamp' => $time,
                'nonceStr' => $result->nonce_str,
                'package' => 'prepay_id='.$result->prepay_id,
                'signType' => 'MD5',
                'paySign' => $paySign,
            );
            return $this->ajaxReturn($data);
        }else{
            return $this->ajaxReturn(['message' => '下单失败']);
        }
    }

    /**
     * 回调
     */
    public function notify(){
        if($this->request->isPost()){
            libxml_disable_entity_loader(true);
            $config = self::getConfig();
            $app = new Application($config);
            $response = $app->payment->handleNotify(function($notify, $successful){
                if ($successful) {
                    $m_pay_log = db('pay_log');
                    $pay_log = $m_pay_log->where(['pay_sn' => $notify->out_trade_no])->find();
                    if(!$pay_log){
                        Log::write('微信支付回调失败，支付单号：'.$notify->out_trade_no.'。原因：找不到支付单','error');
                        return false;
                    }
                    $m_order = db('order');
                    $order = $m_order->where(['id' => $pay_log['record_id']])->find();
                    if(!$order){
                        Log::write('微信支付回调失败，支付单号：'.$notify->out_trade_no.'。原因：找不到订单','error');
                        return false;
                    }else{
                        Db::startTrans();
                        try{
                            $m_order->where([
                                'id' => $pay_log['record_id'],
                                'status' => 0
                            ])->update([
                                'status' => 1,
                                'update_price' => $pay_log['money'],
                                'update_time' => time(),
                            ]);

                            db('order_goods')->where([
                                'order_id' => $pay_log['record_id'],
                                'status' => 0
                            ])->update([
                                'status' => 1
                            ]);

                            $m_pay_log->where([
                                'pay_sn' => $notify->out_trade_no
                            ])->update([
                                'pay_time' => time(),
                                'pay_type'=> 1,
                                'status' => 1
                            ]);
                            $data['type'] = '1';
                            $data['type_name'] = '1';
                            $data['price'] = $pay_log['money'];
                            $data['order_id'] = $pay_log['record_id'];
                            //记录平台金额流水
                            db('platform_amount')->insert($data);
                            Db::commit();
                        }catch (\Exception $e){
                            Db::rollback();
                            Log::write('微信支付回调失败，支付单号：'.$notify->out_trade_no.'。原因：'.$e->getMessage(),'error');
                            return false;
                        }
                    }
                }
                return true; // 返回处理完成
            });

            $response->send();
        }
    }


     /**
     * 退款
     */
    public function wechat_refund($order_id,$refundNo)
    {
        $pay_log = db('pay_log')->where(['record_id' => $order_id, 'status' => 1])->find();

        $refund_result = db('order_return')->where(['refund_sn'=>$refundNo])->field('goods_price,goods_num')->find();

        $config = self::getConfig();
        $config['payment']['notify_url'] = __ROOT__.'/api/pay/wechat/refund/notify';
        $app = new Application($config);
        $payment = $app->payment;
        $result = $payment->refund($pay_log['pay_sn'], $refundNo, $pay_log['money'], $refund_result['goods_price']*$refund_result['goods_num'],$config['payment']['merchant_id'] , 'out_trade_no', 'REFUND_SOURCE_RECHARGE_FUNDS');
        if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS') {
            return true;
        } else{
            Log::write('退款失败：'.$result->err_code_des.',错误码：'.$result->err_code.'退款支付单号：'.$pay_log['pay_sn'],'error');
            return false;
        }
    }


    /**
     * 退款回调
     */
    public function refund_return(){
        // $xmlData = file_get_contents('php://input');
        // libxml_disable_entity_loader(true);
        // $data = json_decode(json_encode(simplexml_load_string($xmlData, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        // if($data['return_code'] == 'SUCCESS'){
        //     $config = self::getConfig();
        //     $key = md5($config['payment']['key']);
        //     $result = $this->refund_decrypt($data['req_info'],$key);
        //     libxml_disable_entity_loader(true);
        //     $info = json_decode(json_encode(simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        //     $m_refund = db('order_return');
        //     if($info['refund_status'] == 'SUCCESS'){
        //         Db::startTrans();
        //         try{
        //             $refund = $m_refund->where(['refund_sn' => $info['out_refund_no']])->find();
        //             if(!$refund) throw new \Exception('找不到退款单');
        //             $m_refund->where(['refund_sn' => $info['out_refund_no']])->update(['money_arrives_status' => '1']);
        //             Db::commit();
        //         }catch (\Exception $e){
        //             Db::rollback();
        //             Log::write('退款回调失败，退款单号：'.$info['out_refund_no'].'，更新数据错误，错误原因：'.$e->getMessage(),'error');
        //             exit;
        //         }
        //         $response = [
        //             'return_code' => 'SUCCESS',
        //             'return_msg' => 'OK',
        //         ];
        //         echo XML::build($response);
        //         exit;
        //     }else{
        //         Log::write('退款回调失败，退款单号：'.$info['out_refund_no'],'error');
        //         $response = [
        //             'return_code' => 'FAIL',
        //         ];
        //         echo XML::build($response);
        //         exit;
        //     }
        // }
    }


    private function refund_decrypt($str, $key) {
        $str = base64_decode($str);
        $str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
        $len = strlen($str);
        $pad = ord($str[$len - 1]);
        return substr($str, 0, strlen($str) - $pad);
    }


    /**
     * 获取订单信息
     */
    public function getPayInfo($pay_sn){
        $pay_log = db('pay_log')->where(['pay_sn' => $pay_sn])->find();
        if(!$pay_log) return array('message' => '找不到支付单');
        if($pay_log['status'] == 1) return array('message' => '该支付单已支付');
        $data = array(
            'pay_sn' => $pay_log['pay_sn'],
            'money' => $pay_log['money'],
            'openid' => $this->user['wx_openid'],
        );
        $order = db('order')->where(['id' => $pay_log['record_id']])->find();
        if(!$order) return array('message' => '找不到订单');
        $data['detail'] = $order['product_name'];
        return $data;
    }
}